﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using TeaCompiler.CodeDom;

namespace TeaCompiler.Parser {

    /// <summary>
    /// 用于生成语法树的工具。
    /// </summary>
    public class Parser {

        #region Internal

        /// <summary>
        /// 当前的词法解析器。
        /// </summary>
        Lexer _lexer;

        /// <summary>
        /// 获取或设置当前的词法解析器。
        /// </summary>
        public Lexer Lexer {
            get {
                return _lexer;
            }
            set {
                _lexer = value;
            }
        }

        /// <summary>
        /// 获取或设置当前转换器是否为严格模式。
        /// </summary>
        public bool IsStrictMode {
            get;
            set;
        }

        /// <summary>
        /// 获取或设置当前错误报告工具。
        /// </summary>
        public IErrorReporter ErrorReporter {
            get;
            set;
        }

        /// <summary>
        /// 获取当前解析有无出现错误的状态。
        /// </summary>
        public bool HasError {
            get {
                return ErrorReporter.ErrorCount > 0;
            }
        }

        void Error(string msg) {
            // ErrorReporter.Error(msg, _lexer.Current.StartLocation, _lexer.Current.EndLocation);
        }

        void Error(string msg, params string[] args) {
            Error(String.Format(msg, args));
        }

        void WarningStrict(string msg) {
            // ErrorReporter.WarningStrict(msg, _lexer.Current.StartLocation, _lexer.Current.EndLocation);
        }

        void WarningStrict(string msg, params string[] args) {
            WarningStrict(String.Format(msg, args));
        }

        void Warning(string msg) {
            //  ErrorReporter.Warning(msg, _lexer.Current.StartLocation, _lexer.Current.EndLocation);
        }

        void Warning(string msg, params string[] args) {
            Warning(String.Format(msg, args));
        }

        /// <summary>
        /// 初始化 <see cref="CorePlus.Parser.Javascript.Parser"/> 的新实例。
        /// </summary>
        public Parser(Lexer lexer, IErrorReporter errorReportor) {
            _lexer = lexer;
            ErrorReporter = errorReportor;
        }

        /// <summary>
        /// 初始化 <see cref="CorePlus.Parser.Javascript.Parser"/> 的新实例。
        /// </summary>
        public Parser(IErrorReporter errorReportor)
            : this(new Lexer(), errorReportor) {
        }

        /// <summary>
        /// 初始化 <see cref="CorePlus.Parser.Javascript.Parser"/> 的新实例。
        /// </summary>
        public Parser()
            : this(new Lexer(), new DefaultErrorReporter()) {
        }

        /// <summary>
        /// 解析指定的文档 。
        /// </summary>
        /// <param name="souceCode">要操作的字符串。</param>
        /// <returns></returns>
        public Module ParseString(string souceCode) {
            return Parse(new StringReader(souceCode));
        }

        public Module ParseFile(string fileName, Encoding encoding = null) {
            using (StreamReader sb = new StreamReader(fileName, encoding ?? Encoding.UTF8))
                return Parse(sb);
        }

        public Module ParseUri(Uri uri, Encoding encoding = null) {
            System.Net.WebRequest req = System.Net.HttpWebRequest.Create(uri);
            return ParseStream(req.GetResponse().GetResponseStream(), encoding);
        }

        public Module ParseStream(Stream stream, Encoding encoding = null) {
            return Parse(new StreamReader(stream, encoding ?? Encoding.UTF8));
        }

        /// <summary>
        /// 解析指定的文档 。
        /// </summary>
        /// <param name="souceCode">要操作的字符串。</param>
        /// <returns></returns>
        public Module Parse(TextReader source) {
            ErrorReporter.Clear();
            _lexer.Source = source;
            Module module = new Module() {
                StartLocation = _lexer.Peek().StartLocation,
                Statements = new List<Statement>()
            };
            ParseProgram(module);
            module.EndLocation = _lexer.Current.EndLocation;
            return module;
        }

        ///// <summary>
        ///// 解析指定的扫描器。可选是否返回函数或脚本。
        ///// </summary>
        ///// <param name="source">要解析的源。</param>
        ///// <param name="sourceName">源名，如果是函数，则为函数名。否则是脚本名。</param>
        ///// <param name="returnFunction">如果是 true， 则返回函数。否则返回脚本。</param>
        ///// <returns>解析的结果。实现 IScope 的实例。</returns>
        //public IScopeNode Parse(TextBuffer source, bool returnFunction) {

        //    _lexer.Source = source;

        //    if (returnFunction) {
        //        return Parse(new FunctionExpression(String.Empty, new List<Identifier>(), _lexer.Peek().StartLocation));
        //    } else {
        //        return Parse(new Script(_lexer.Peek().StartLocation));
        //    }
        //}

        ///// <summary>
        ///// 进行解析。
        ///// </summary>
        //public FunctionExpression Parse(FunctionExpression fn) {

        //    //  ParseProgram(fn);

        //    fn.endLocation = _lexer.Current.EndLocation;

        //    return fn;

        //}

        #endregion

        #region Scope

        /// <summary>
        /// 当前作用域。
        /// </summary>
        IScope _currentScope;

        /// <summary>
        /// 当前正在使用的修饰符。
        /// </summary>
        Modifier _currentModifiers;

        /// <summary>
        /// 获取当前的脚本域。
        /// </summary>
        public IScope CurrentScript {
            get {
                return _currentScope;
            }
        }

        /// <summary>
        /// 表示进入可中断循环(比如 break/continue 能直接搜索的)。
        /// </summary>
        /// <param name="loopLabel"></param>
        /// <param name="doPushScope"></param>
        /// <returns></returns>
        private void EnterScope(IScope newScope) {
            _currentScope = newScope;
            //block.Parent = _breakableBlock;
            //_breakableBlock = block;
        }

        /// <summary>
        /// 表示离开一个中断循环块。
        /// </summary>
        private void ExitScope() {
            // _breakableBlock = _breakableBlock.Parent;
        }

        void DefineSymbol(TokenType declType, bool disallowIn, string name) {
            //IScopeNode lastBlock = _currentScope.GetDefinedBlock(name);
            //if (lastBlock != null && (declType == TokenType.Const || lastBlock.GetSymbol(name) == TokenType.Const)) {
            //    Error(Messages.ConstMultiDeclared, name);
            //} else {
            //    switch (declType) {
            //        case TokenType.Var:
            //        case TokenType.Const:
            //        case TokenType.Function:
            //            if (lastBlock != null) {

            //                if (IsStrictMode) {
            //                    switch (lastBlock.GetSymbol(name)) {
            //                        case TokenType.Var:

            //                            WarningStrict(Messages.VarMultiDeclared, name);
            //                            break;

            //                        case TokenType.LParam:
            //                            WarningStrict(Messages.VarHideArguments, name);
            //                            break;
            //                    }
            //                }
            //            } else {
            //                _currentScope.AddSymbol(name, declType);
            //            }
            //            break;

            //        case TokenType.LParam:
            //            if (lastBlock != null) {
            //                // must be duplicate parameter. Second parameter hides the 
            //                // first, so go ahead and add the second pararameter
            //                Warn(Messages.DumpParam, name);
            //            }
            //            _currentScope.AddSymbol(name, declType);
            //            break;
            //        case TokenType.Let:
            //            if (lastBlock != null && lastBlock.GetSymbol(name) == TokenType.Let) {
            //                Error(Messages.DumpParam, name);
            //            }
            //            _currentScope.AddSymbol(name, declType);
            //            break;

            //        default:
            //            break;
            //    }
            //}
        }

        #endregion

        #region Detect

        /// <summary>
        /// 如果下一个操作符和指定的操作符 <paramref name="token"/> 一致， 则移动到下一个操作符 。
        /// </summary>
        /// <param name="token">需要获取的操作符 。</param>
        /// <returns>如果当前操作符符合指定的操作符且移动位置， 返回 true; 否则返回 false 。</returns>
        bool MatchToken(TokenType token) {
            if (_lexer.Peek().Type == token) {
                _lexer.Read();
                return true;
            }

            return false;
        }

        /// <summary>
        /// 确认下一个标识符是指定的标识符<paramref name="token"/>。
        /// </summary>
        /// <param name="token">期待的下一个操作符。</param>
        /// <param name="message">错误信息。</param>
        void AssertToken(TokenType token) {
            if (_lexer.Peek().Type != token) {
                //   Error(String.Format(Messages.ExpectedToken, Token.Find(token).Name));
            }
        }

        /// <summary>
        /// 确保下一个 Token 为指定的 <paramref name="token"/> ，否则输出错误。
        /// </summary>
        /// <param name="token">期待的下一个操作符。</param>
        /// <param name="message">错误信息。</param>
        void ExpectToken(TokenType token, string message) {
            if (_lexer.Peek().Type != token) {
                Error(message);
            } else {
                _lexer.Read();
            }
        }

        /// <summary>
        /// 确保下一个 Token 为指定的 <paramref name="token"/> ，否则输出错误。
        /// </summary>
        /// <param name="token">期待的下一个操作符。</param>
        Token ExpectToken(TokenType token) {
            if (_lexer.Peek().Type != token) {
                //  Error(String.Format(Messages.ExpectedToken, Token.Find(token).Name));
                return _lexer.Current;
            } else {
                return _lexer.Read();
            }
        }

        ///// <summary>
        ///// 判断接下来的表达式是否只能作为表达式的一部分使用。
        ///// </summary>
        ///// <param name="peekLocation"></param>
        ///// <returns></returns>
        //private bool LookslikeBodyOfExpression(int peekLocation) {
        //    var type = _lexer.Peek(peekLocation).Type;

        //    if (type >= TokenType.PeriodChain && type <= TokenType.OrReturn) {
        //        return true;
        //    }


        //    return false;
        //}

        //private bool LookslikeTypeInternal(bool isDeclaration, out int peekLocation) {

        //    // 如果是系统内置类型变量，则一定是类型。
        //    if (IsPredefinedType(_lexer.Current.LiteralBuffer)) {
        //        peekLocation = 1;
        //        return true;
        //    }

        //    peekLocation = 0;

        //    int gernicCount = 0;
        //checknext:
        //    switch (_lexer.Peek(++peekLocation).Type) {
        //        case TokenType.Period:
        //            goto checknext;
        //        case TokenType.Mul: {
        //                var type = _lexer.Peek(peekLocation).Type;

        //                if (type == TokenType.Identifier) {
        //                    return isDeclaration;
        //                }

        //                if (type >= TokenType.PeriodChain && type <= TokenType.OrReturn) {
        //                    return true;
        //                }

        //                return false;
        //            }

        //        case TokenType.LBrack:
        //            if (_lexer.Peek(peekLocation + 1).Type == TokenType.RBrack) {
        //                return true;
        //            }
        //            return false;
        //        case TokenType.Lt:
        //    }

        //}

        private bool LookslikeGernicType() {

            int peekLocation = 0;
            int ltCount = 1;
            bool allowComma = false;

        checknext:

            switch (_lexer.Peek(++peekLocation).Type) {
                case TokenType.Identifier:
                    allowComma = true;
                    goto checknext;
                case TokenType.Period:
                    allowComma = false;
                    goto checknext;
                case TokenType.Comma:
                    if (allowComma) {
                        allowComma = false;
                        goto checknext;
                    }
                    break;
                case TokenType.Lt:
                    ltCount++;
                    allowComma = false;
                    goto checknext;
                case TokenType.Gt:
                    ltCount--;
                    if (ltCount == 0) {
                        return true;
                    }

                    allowComma = true;
                    goto checknext;
                case TokenType.Shr:
                    ltCount--;
                    if (ltCount == 0) {
                        return true;
                    }

                    goto case TokenType.Gt;

            }


            return false;
        }

        private bool LookslikeFunctionLiteral() {
            int lp = 1;
            int peekLocation = 1;

            for (; ; ) {
                switch (_lexer.Peek(peekLocation++).Type) {
                    case TokenType.LParam:
                        lp++;
                        break;
                    case TokenType.RParam:
                        lp--;
                        if (lp == 0) {

                            TokenType type = _lexer.Peek(peekLocation).Type;

                            if (type == TokenType.Lambda) {
                                return true;
                            }

                            return false;
                        }
                        break;
                    case TokenType.EOF:
                        return false;
                }

            }

            return false;
        }

        private bool ConsiderAsCast(Expression left) {

            // 如果左边肯定是一个类型，或者右边是独立的，则认为是类型转换。
            if (left is TypeExpression) {
                return true;
            }

            // 如果左边是系统类型，则认为是类型转换。
            Identifier identifier = left as Identifier;
            if (identifier != null && TokenInfo.IsPredefinedType(identifier.Name)) {
                return true;
            }

            if (identifier == null && !(left is PropertyCallExpression)) {
                return false;
            }

            return LookslikeUnaryExpression();
        }

        private bool LookslikeUnaryExpression() {
            TokenType type = _lexer.Peek().Type;
            if (type >= TokenType.Identifier && type <= TokenType.FloatLiteral) {
                return true;
            } else if (type >= TokenType.StringLiteral && type <= TokenType.DataLiteral) {
                return true;
            } else if (type >= TokenType.Typeof && type <= TokenType.Trace) {
                return true;
            }
            switch (type) {
                case TokenType.LParam:
                case TokenType.New:
                case TokenType.LBrack:
                case TokenType.This:
                case TokenType.Base:
                    return true;
                default:
                    return false;
            }
        }

        private static bool MatchString(StringBuilder stringBuilder, string p) {
            if (stringBuilder.Length != p.Length) {
                return false;
            }

            for (int i = 0; i < p.Length; i++) {
                if (stringBuilder[i] != p[i]) {
                    return false;
                }
            }


            return true;

        }

        #endregion

        #region Statement

        private void ParseProgram(IScope scope) {

            //  Program :
            //    StatementList

            _currentScope = scope;

            ParseStatementList(scope);

        }

        private void ParseStatementList(IScope scope) {

            //  StatementList :
            //    Statement
            //    StatementList Statement

            for (; ; ) {

                _lexer.HasRead = false;

                switch (_lexer.Peek().Type) {

                    case TokenType.RBrace:

                        // 如果是内部脚本块，则发现 RBrace 时中停止解析。
                        if (scope.Module != scope) {
                            return;
                        }

                        Error("多余的 }");
                        _lexer.Read();
                        break;

                    case TokenType.EOF:
                        return;

                    default:
                        scope.Statements.Add(ParseStatement());
                        break;

                }

                // 如果没有任何分支可以进入，则自动忽略标签直到换行或分号。
                if (!_lexer.HasRead) {

                    Token t;

                    do {
                        _lexer.Read();
                        t = _lexer.Peek();
                    } while (t.Type != TokenType.Semicolon && t.Type != TokenType.EOF);

                }

            }

        }

        private Statement ParseStatement() {

            //  Statement :
            //    Block
            //    VariableStatement
            //    EmptyStatement
            //    ExpressionStatement
            //    SelectionStatement
            //    IterationStatement
            //    JumpStatement
            //    NativeStatement
            //    LabelledStatement
            //    LockStatement
            //    TryStatement
            //    LetStatement
            //    DebuggerStatement
            //    ImportStatement
            //    Semicolon

            //  SelectionStatement :
            //    IfStatement
            //    SwitchStatement

            //  IterationStatement :
            //    ForStatement
            //    ForInStatemeent
            //    ForToStatemeent
            //    DoWhileStatemeent
            //    WhileStatemeent

            //  JumpStatement :
            //    ContinueStatement
            //    BreakStatement
            //    ReturnStatement
            //    GotoStatement
            //    ThrowStatement 

            TokenType tokenType = _lexer.Peek().Type;
        skip:
            switch (tokenType) {

                case TokenType.Identifier: {

                        // Identifier Identifier
                        // Identifier[] Identifier
                        // Identifier<A> Identifier
                        // Identifier:
                        // Identifier.Expression
                        // Identifier => A

                        Expression typeOrExpression = ParseTypeOrExpression(true);

                        switch (_lexer.Peek().Type) {
                            case TokenType.Identifier:
                                return ParseVariableStatement(typeOrExpression);
                            case TokenType.Colon: {
                                    Identifier id = typeOrExpression as Identifier;
                                    if (id != null) {
                                        return ParseLabelledStatement(id);
                                    }

                                    goto default;
                                }
                            default:
                                return ParseExpressionStatement(typeOrExpression);
                        }

                    }

                case TokenType.LBrace:
                    return ParseBlock();

                case TokenType.Var:
                    return ParseVariableStatement();

                case TokenType.If:
                    return ParseIfStatement();

                case TokenType.Switch:
                    return ParseSwitchStatement();

                case TokenType.While:
                    return ParseWhileStatement();

                case TokenType.Do:
                    return ParseDoWhileStatement();

                case TokenType.For:
                    return ParseForStatement();

                case TokenType.Try:
                    return ParseTryStatement();

                case TokenType.Throw:
                    return ParseThrowStatement();

                case TokenType.Break:
                    return ParseBreakStatement();

                case TokenType.Continue:
                    return ParseContinueStatement();

                case TokenType.Goto:
                    return ParseGotoStatement();

                case TokenType.Let:
                    return ParseLetStatement();

                case TokenType.Return:
                    return ParseReturnStatement();

                case TokenType.Import:
                    return ParseImportStatement();

                case TokenType.Debugger:
                    return ParseDebuggerStatement();

                case TokenType.Semicolon:
                    return new Semicolon() {
                        StartLocation = _lexer.Read().StartLocation
                    };

                case TokenType.Function:
                //    return ParseFunctionDeclaration();

                case TokenType.Const:
                    _currentModifiers |= Modifier.Const;
                    _lexer.Read();
                    tokenType = _lexer.Peek().Type;
                    if (tokenType == TokenType.Identifier) {
                        return ParseVariableStatement();
                    }
                    goto skip;

                case TokenType.Public:
                    _currentModifiers |= Modifier.Public;
                    _lexer.Read();
                    tokenType = _lexer.Peek().Type;
                    goto skip;

                case TokenType.Protected:
                    _currentModifiers |= Modifier.Protected;
                    _lexer.Read();
                    tokenType = _lexer.Peek().Type;
                    goto skip;

                case TokenType.Private:
                    _currentModifiers |= Modifier.Private;
                    _lexer.Read();
                    tokenType = _lexer.Peek().Type;
                    goto skip;

                case TokenType.Internal:
                    _currentModifiers |= Modifier.Internal;
                    _lexer.Read();
                    tokenType = _lexer.Peek().Type;
                    goto skip;

                case TokenType.Final:
                    _currentModifiers |= Modifier.Final;
                    _lexer.Read();
                    tokenType = _lexer.Peek().Type;
                    goto skip;

                case TokenType.Static:
                    _currentModifiers |= Modifier.Static;
                    _lexer.Read();
                    tokenType = _lexer.Peek().Type;
                    goto skip;

                case TokenType.Abstract:
                    _currentModifiers |= Modifier.Abstract;
                    _lexer.Read();
                    tokenType = _lexer.Peek().Type;
                    goto skip;

                case TokenType.Virtual:
                    _currentModifiers |= Modifier.Virtual;
                    _lexer.Read();
                    tokenType = _lexer.Peek().Type;
                    goto skip;

                case TokenType.Override:
                    _currentModifiers |= Modifier.Override;
                    _lexer.Read();
                    tokenType = _lexer.Peek().Type;
                    goto skip;

                case TokenType.Once:
                    _currentModifiers |= Modifier.Once;
                    _lexer.Read();
                    tokenType = _lexer.Peek().Type;
                    goto skip;

                case TokenType.Illegal:
                    Error(_lexer.Current.LiteralBuffer.ToString());
                    _lexer.Read();
                    return ParseStatement();

                case TokenType.EOF:
                    return new EmptyStatement() {
                        StartLocation = _lexer.Peek().StartLocation
                    };

                default:
                    return ParseExpressionStatement();
            }

        }

        private Statement ParseStatementExceptEmptyStatement() {
            Statement s = ParseStatement();

            if (s.IsEmpty) {
                Error("应输入语句");
            }

            return s;
        }

        private Block ParseBlock() {

            //  Block :
            //    { StatementList? }

            Block ret = new Block() {
                StartLocation = _lexer.Read().StartLocation,
                Statements = new List<Statement>()
            };

            //  EnterScope(ret);
            ParseStatementList(ret);
            //   ExitScope();
            ExpectToken(TokenType.RBrace);
            ret.EndLocation = _lexer.Current.EndLocation;
            return ret;

        }

        private VariableStatement ParseVariableStatement() {

            //  VariableStatement :
            //    Modifier VariableDeclarationList
            //    Modifier? var VariableDeclarationList
            //    Modifier? const VariableDeclarationList
            //    Modifier? Type VariableDeclarationList

            VariableStatement ret = new VariableStatement() {
                StartLocation = _lexer.Read().StartLocation,
                Modifier = _currentModifiers
            };

            _currentModifiers = Modifier.None;

            ret.Variables = ParseVariableDeclarationList();

            ret.EndLocation = _lexer.Current.EndLocation;

            return ret;
        }

        private VariableStatement ParseVariableStatement(Expression type) {

            //  VariableStatement :
            //    Modifier VariableDeclarationList
            //    Modifier? var VariableDeclarationList
            //    Modifier? const VariableDeclarationList
            //    Modifier? Type VariableDeclarationList

            _lexer.Read();

            VariableStatement ret = new VariableStatement() {
                StartLocation = type.StartLocation,
                Modifier = _currentModifiers,
                Type = type
            };

            _currentModifiers = Modifier.None;

            ret.Variables = ParseVariableDeclarationList();

            ret.EndLocation = _lexer.Current.EndLocation;

            return ret;
        }

        private List<VariableStatement.VariableDeclaration> ParseVariableDeclarationList() {

            //  VariableDeclarationList :
            //    VariableDeclaration
            //    VariableDeclarationList , VariableDeclaration

            //  VariableDeclaration :
            //    Identifier VariableInitialiser?

            //  VariableInitialiser :
            //    = AssignmentExpression

            List<VariableStatement.VariableDeclaration> ret = new List<VariableStatement.VariableDeclaration>();

            do {

                VariableStatement.VariableDeclaration v = new VariableStatement.VariableDeclaration() {
                    Name = new Identifier() {
                        StartLocation = ExpectToken(TokenType.Identifier).StartLocation,
                        Name = _lexer.Current.LiteralBuffer.ToString(),
                        EndLocation = _lexer.Current.EndLocation
                    }
                };

                if (MatchToken(TokenType.Assign)) {
                    v.Initialiser = ParseExpression((byte)(TokenType.Comma + 1));
                }

                ret.Add(v);

            } while (MatchToken(TokenType.Comma));

            return ret;

        }

        private ExpressionStatement ParseExpressionStatement() {

            //  ExpressionStatement :
            //    [lookahead ∉ {{, function, Type}] Expression ;

            return ParseExpressionStatementInternal(ParseExpression());

        }

        private ExpressionStatement ParseExpressionStatement(Expression left) {

            //  ExpressionStatement :
            //    [lookahead ∉ {{, function, Type}] Expression ;

            return ParseExpressionStatementInternal(ParseExpression(left));

        }

        private ExpressionStatement ParseExpressionStatementInternal(Expression e) {

            return new ExpressionStatement() {
                Expression = e
            };

            //// 如果紧接的不是 ; ，则设置此语句为 MissingSemicolon 。
            //if (_lexer.Current.Type != TokenType.Semicolon) {
            //    ret.MissingSemicolon = true;
            //}

            //   CheckExpressionStatement();

            //// 严格模式下。
            //if (IsStrictMode) {

            //    // 检查是否无分号。
            //    if (ret.MissingSemicolon) {
            //        WarningStrict("MissingSemicolon");
            //    }

            //    // 检查是否有意义。
            //    if (!ret.HasSideEffects) {
            //        WarningStrict("HasSideEffects");
            //    }
            //}


            //Expression type = ParseType();
            //if (type == null) {

            //}

            //if (!_lexer.HasLineTerminatorBeforeNext) {
            //    switch (_lexer.Peek().Type) {
            //        case TokenType.Semicolon:
            //        case TokenType.EOF:
            //        case TokenType.RBrace:
            //            break;

            //        case TokenType.In:
            //            if (disallowIn)
            //                break;

            //            goto default;

            //        default:
            //            Error(Messages.UnexpectedToken, Token.IsSymbol(_lexer.Peek().Type) ? Token.Find(_lexer.Peek().Type).Name : _lexer.Peek().Literal);
            //            break;
            //    }
            //}
        }

        private IfStatement ParseIfStatement() {

            //  IfStatement :
            //    if Expression Statement
            //    if Expression Statement else Statement

            IfStatement ret = new IfStatement() {
                StartLocation = _lexer.Read().StartLocation,
                Condition = ParseCondition(),
                Then = ParseStatementExceptEmptyStatement()
            };

            if (MatchToken(TokenType.Else)) {
                ret.Else = ParseStatementExceptEmptyStatement();
            }

            ret.EndLocation = _lexer.Current.EndLocation;

            return ret;
        }

        private SwitchStatement ParseSwitchStatement() {
            return null;
            //    //  SwitchStatement :
            //    //    switch ( Expression ) CaseBlock

            //    // CaseBlock :
            //    //    { CaseClausesopt }
            //    //    { CaseClausesopt DefaultClause CaseClausesopt }

            //    //  CaseClauses :
            //    //    CaseClause
            //    //    CaseClauses CaseClause

            //    // CaseClause :
            //    //    case Expression : StatementListopt

            //    // DefaultClause :
            //    //    default : StatementListopt

            //    //Location current = _lexer.Read().StartLocation;
            //    //ExpectToken(TokenType.LParam);
            //    //SwitchStatement ret = new SwitchStatement(statementLabel, new NodeList<CaseClause>(), ParseExpression(false), current);

            //    //EnterBlock(ret);
            //    //try {
            //    //    ExpectToken(TokenType.RParam);
            //    //    ExpectToken(TokenType.LBrace);

            //    //    bool hasDefault = false;
            //    //    for (; ; ) {
            //    //        Expression ep;
            //    //        TokenInfo tk = _lexer.Read();
            //    //        current = tk.StartLocation;
            //    //        TokenType tokenType = tk.Type;
            //    //        switch (tokenType) {
            //    //            case TokenType.Case:
            //    //                ep = ParseExpression(false);
            //    //                ExpectToken(TokenType.Colon);
            //    //                break;

            //    //            case TokenType.Default:
            //    //                if (hasDefault) {
            //    //                    Error(Messages.MultiDefault);
            //    //                } else {
            //    //                    hasDefault = true;
            //    //                }
            //    //                ep = null;
            //    //                ExpectToken(TokenType.Colon);
            //    //                break;

            //    //            case TokenType.RBrace:
            //    //                goto endLoop;

            //    //            default:
            //    //                Error(Messages.BadSwitch);
            //    //                goto endLoop;
            //    //        }


            //    //        CaseClause caseExpression = new CaseClause(ep, current, _lexer.Current.EndLocation);
            //    //        while ((tokenType = _lexer.Peek().Type) != TokenType.RBrace
            //    //               && tokenType != TokenType.Case
            //    //               && tokenType != TokenType.Default
            //    //               && tokenType != TokenType.EOF) {
            //    //            caseExpression.Statements.Add(ParseStatement());
            //    //        }

            //    //        ret.Cases.Add(caseExpression);
            //    //    }


            //    //endLoop:
            //    //    ret.endLocation = _lexer.Current.EndLocation;
            //    //} finally {
            //    //    ExitBlock();
            //    //}
            //    //return ret;
        }

        private ForStatement ParseForStatement() {

            //  ForStatement :
            //    for (InitStatement?; Expression? ; Expression? ) Statement
            //    ForInStatement
            //    ForToStatement

            //  ForInStatement :
            //    for (Type Identifier in ExpressionNotIn) Statement
            //    for (var Identifier in ExpressionNotIn) Statement
            //    for (Identifier in ExpressionNotIn) Statement

            //  ForToStatement :
            //    for (Type Identifier = ExpressionNotTo to ExpressionNotTo) Statement
            //    for (var Identifier = ExpressionNotTo to ExpressionNotTo) Statement
            //    for (Identifier = ExpressionNotTo to ExpressionNotTo) Statement

            //  ExpressionNotIn:
            //    Expression [peek ∉ {in}]

            //  ExpressionNotTo:
            //    Expression [peek ∉ {to}] 

            //bool seenIn = false, seenTo = false;

            //int peekToken = 1;
            //for (; ; ) {
            //    switch (_lexer.Peek(peekToken).Type) {
            //        case TokenType.Semicolon:
            //        case TokenType.LBrace:
            //    }
            //}

            //Location startLocation = _lexer.Read().StartLocation;
            //Statement initStatement = null;

            //switch (_lexer.Peek().Type) {
            //    case TokenType.Identifier: {

            //            // Identifier Identifier
            //            // Identifier[] Identifier
            //            // Identifier<A> Identifier
            //            // Identifier:
            //            // Identifier.Expression
            //            // Identifier => A

            //            Expression typeOrExpression = ParseTypeOrExpression(true);

            //            switch (_lexer.Peek().Type) {
            //                case TokenType.Identifier:
            //                    return ParseVariableStatement(typeOrExpression);
            //                case TokenType.Colon: {
            //                        Identifier id = typeOrExpression as Identifier;
            //                        if (id != null) {
            //                            return ParseLabelledStatement(id);
            //                        }

            //                        goto default;
            //                    }
            //                default:
            //                    return ParseExpressionStatement(typeOrExpression);
            //            }

            //        }
            //    case TokenType.Var:
            //    case TokenType.Semicolon:
            //        break;
            //    default:
            //        Error("此处不应该有 {0}", _lexer.Peek().ToString());
            //        break;
            //}

            //if (_lexer.Peek().Type != TokenType.Semicolon) {
            //    initStatement = ParseInitStatement();
            //    if (_lexer.Peek().Type != TokenType.Semicolon) {

            //        BinaryExpression initExpression = null;

            //        if (initStatement is VariableStatement) {
            //            VariableStatement t = (VariableStatement)initStatement;
            //            initExpression = t.Variables[t.Variables.Count - 1].Initialiser as BinaryExpression;
            //        } else if (initStatement is ExpressionStatement) {
            //            AssignmentExpression t = ((ExpressionStatement)initStatement).Expression as AssignmentExpression;
            //            if (t != null && t.Operator == TokenType.Eq) {

            //                initExpression = t.Right as BinaryExpression;
            //            }

            //        }


            //        if (initExpression != null) {
            //            if (initExpression.Operator == TokenType.In) {

            //                ForInStatement ret = new ForInStatement() {
            //                    StartLocation = startLocation,
            //                    Condition = initExpression.Right,
            //                    Each = initStatement
            //                };

            //            } else if (initExpression.Operator == TokenType.To) {

            //            }
            //        }


            //    }
            //}

            return null;
            //Location current = _lexer.Read().StartLocation;

            //IterationStatement np;
            //Statement initStatement;
            //Expression condition;
            //Expression nextStatement = null;

            //ExpectToken(TokenType.LParam);

            //switch (_lexer.Peek().Type) {
            //    case TokenType.Semicolon:
            //        initStatement = new EmptyStatement(_lexer.Current.EndLocation);
            //        break;

            //    case TokenType.Var:
            //    case TokenType.Let:
            //        initStatement = ParseVariableStatement(true);
            //        break;

            //    default:
            //        initStatement = ParseExpressionStatement(true);
            //        break;

            //}

            //// 检查 for( in )
            //if (MatchToken(TokenType.In)) {

            //    // 目标对象。
            //    condition = ParseExpression(false);

            //    np = new ForInStatement(statementLabel, initStatement, condition, current);


            //} else {
            //    // for (;;)
            //    ExpectToken(TokenType.Semicolon);
            //    if (_lexer.Peek().Type == TokenType.Semicolon) {
            //        // no loop condition
            //        condition = new UndefinedExpression();
            //    } else {
            //        condition = ParseExpression(false);
            //    }

            //    ExpectToken(TokenType.Semicolon);
            //    if (_lexer.Peek().Type == TokenType.RParam) {
            //        nextStatement = new UndefinedExpression();
            //    } else {
            //        nextStatement = ParseExpression(false);
            //    }

            //    np = new ForStatement(statementLabel, initStatement, condition, nextStatement, current);
            //}


            //ExpectToken(TokenType.RParam);

            //EnterBlock(np);

            //try {
            //    np.Body = ParseStatementNotEmpty();


            //} finally {
            //    ExitBlock();
            //}

            //return np;
        }

        private DoWhileStatement ParseDoWhileStatement() {
            return null;
            //    // DoWhileStatement :
            //    //   do Statement while ( Expression );

            //    //DoWhileStatement ret = new DoWhileStatement(statementLabel, _lexer.Read().StartLocation);

            //    //EnterBlock(ret);

            //    //try {
            //    //    ret.Body = ParseStatementNotEmpty();
            //    //    ExpectToken(TokenType.While);
            //    //    ret.Condition = ParseCondition();

            //    //    ret.endLocation = _lexer.Current.EndLocation;
            //    //} finally {
            //    //    ExitBlock();
            //    //}


            //    //MatchToken(TokenType.Semicolon);

            //    //ret.endLocation = _lexer.Current.EndLocation;



            //    //return ret;
        }

        private WhileStatement ParseWhileStatement() {
            return null;
            // WhileStatement :
            //   while ( Expression ) Statement

            //WhileStatement ret = new WhileStatement(statementLabel, _lexer.Read().StartLocation);

            //EnterBlock(ret);
            //try {
            //    ret.Condition = ParseCondition();
            //    ret.Body = ParseStatementNotEmpty();
            //    return ret;
            //} finally {
            //    ExitBlock();
            //}
        }

        private Expression ParseCondition() {
            // Condition :
            //    ExpressionExceptFunctionLiteral
            //    ( Expression )

            Expression ret;

            if (MatchToken(TokenType.LParam)) {
                ret = ParseExpression();
                ExpectToken(TokenType.RParam);
            } else {
                ret = ParseExpression();
            }

            // 对 if (a = 7) ... 语句 报错。

            if (IsStrictMode && ret is AssignmentExpression) {
                Warning("AssignCondition");
            }

            return ret;
        }

        private ThrowStatement ParseThrowStatement() {

            //  ThrowStatement :
            //    throw Expression? ;

            return new ThrowStatement() {
                StartLocation = _lexer.Read().StartLocation,
                Expression = ParseExpression()
            };
        }

        private BreakStatement ParseBreakStatement() {

            //  BreakStatement :
            //    break [no LineTerminator here] Identifier? ;

            BreakStatement ret = new BreakStatement() {
                StartLocation = _lexer.Read().StartLocation
            };

            if (!_lexer.Peek().HasLineTerminatorBeforeStart && _lexer.Peek().Type == TokenType.Identifier) {
                ret.Label = _lexer.Read().LiteralBuffer.ToString();
            }

            ret.EndLocation = _lexer.Current.EndLocation;

            return ret;
        }

        private GotoStatement ParseGotoStatement() {

            //  GotoStatement :
            //    goto Identifier ;

            return new GotoStatement() {
                StartLocation = _lexer.Read().StartLocation,
                Label = ExpectToken(TokenType.Identifier).LiteralBuffer.ToString(),
                EndLocation = _lexer.Current.EndLocation
            };
        }

        private ContinueStatement ParseContinueStatement() {

            //  ContinueStatement :
            //    continue [no LineTerminator here] Identifier? ;

            ContinueStatement ret = new ContinueStatement() {
                StartLocation = _lexer.Read().StartLocation
            };

            if (!_lexer.Peek().HasLineTerminatorBeforeStart && _lexer.Peek().Type == TokenType.Identifier) {
                ret.Label = _lexer.Read().LiteralBuffer.ToString();
            }

            ret.EndLocation = _lexer.Current.EndLocation;

            return ret;
        }

        private Statement ParseImportStatement() {

            throw new NotImplementedException();
        }

        private DebuggerStatement ParseDebuggerStatement() {

            //  DebuggerStatement:
            //     debugger [no LineTerminator here] Expression?

            DebuggerStatement ret = new DebuggerStatement() {
                StartLocation = _lexer.Current.StartLocation
            };
            if (!_lexer.Current.HasLineTerminatorBeforeStart) {
                _lexer.Read();
                ret.Condition = ParseExpression();
            }

            return ret;

        }

        private ReturnStatement ParseReturnStatement() {

            //  ReturnStatement :
            //    return Expression? ;

            return new ReturnStatement() {
                StartLocation = _lexer.Read().StartLocation,
                Expression = ParseExpression()
            };

        }

        private LabelledStatement ParseLabelledStatement(Identifier label) {

            //  LabelledStatement :
            //    Identifier : Statement

            LabelledStatement ret = new LabelledStatement() {
                StartLocation = _lexer.Read().StartLocation,
                Label = _lexer.Current.LiteralBuffer.ToString()
            };

            _lexer.Read();
            ret.Statement = ParseStatement();

            return ret;
        }

        private TryStatement ParseTryStatement() {
            return null;
            // try {
            //   ...
            // } catch(e) {
            //   ...
            // } finally {
            //   ...
            // }

            //    // 跳过 try
            //    Location current = _lexer.Read().StartLocation;

            //    AssertToken(TokenType.LBrace);


            //    Block tryblock = ParseBlock();

            //    string varName = null;

            //    Block catchblock = null;

            //    Block finallyblock = null;

            //redo:

            //    switch (_lexer.Peek().Type) {
            //        case TokenType.Catch:
            //            if (catchblock != null) {
            //                Error(Messages.MultiCatch);
            //            }

            //            _lexer.Read();
            //            ExpectToken(TokenType.LParam);

            //            ExpectToken(TokenType.Identifier);
            //            varName = _lexer.Current.Literal;

            //            ExpectToken(TokenType.RParam);

            //            catchblock = ParseBlock();

            //            goto redo;

            //        case TokenType.Finally:
            //            _lexer.Read();
            //            finallyblock = ParseBlock();
            //            break;
            //    }

            //    if (finallyblock == null) {

            //        if (catchblock == null) {
            //            Error(Messages.NoCatchOrFinally);
            //            catchblock = new Block();
            //        }
            //        return new TryCatchStatement(tryblock, varName, catchblock, current);

            //    }

            //    if (catchblock == null)
            //        return new TryFinallyStatement(tryblock, finallyblock, current);

            //    return new TryCatchFinallyStatement(tryblock, varName, catchblock, finallyblock, current);



        }

        private LetStatement ParseLetStatement() {

            //  LetStatement :
            //    let InitStatement Statement

            return new LetStatement() {
                StartLocation = _lexer.Read().StartLocation,
                InitStatement = ParseInitStatement(),
                Body = ParseStatementExceptEmptyStatement(),
                EndLocation = _lexer.Current.EndLocation
            };

        }

        private Statement ParseInitStatement() {

            //  InitStatement :
            //    VariableStatement
            //    ExpressionStatement

            Statement s = ParseStatement();

            if (!(s is VariableStatement) && !(s is ExpressionStatement)) {
                Error("需要变量定义语句");
            }

            return s;
        }

        #endregion

        #region Expression

        /// <summary>
        /// 解析表达式。
        /// </summary>
        /// <returns>表达式节点。</returns>
        private Expression ParseExpression(byte currentPrecedence = 1) {

            //  UnaryExpression :
            //    PostfixExpression
            //    delete UnaryExpression
            //    await UnaryExpression
            //    typeof UnaryExpression
            //    ++ UnaryExpression
            //    -- UnaryExpression
            //    + UnaryExpression
            //    - UnaryExpression
            //    ~ UnaryExpression
            //    ! UnaryExpression
            //    ( Type ) UnaryExpression
            //    * UnaryExpression
            //    & UnaryExpression

            TokenType type = _lexer.Peek().Type;

            Expression left;

            if (type == TokenType.Identifier) {

                left = ParseTypeOrExpression(false);

            } else if (type == TokenType.LParam) {
                if (LookslikeFunctionLiteral()) {
                    left = ParseFunctionLiteral();
                } else {

                    Location start = _lexer.Read().StartLocation;

                    left = ParseExpression();

                    ExpectToken(TokenType.RParam);

                    // 检查是否有类型转换。
                    if (ConsiderAsCast(left)) {
                        left = new CastExpression() {
                            StartLocation = start,
                            Left = left,
                            Operator = TokenType.LParam,
                            Right = ParseExpression()
                        };
                    } else {
                        left = new ParenthesizedExpression() {
                            StartLocation = start,
                            Expression = left,
                            EndLocation = _lexer.Current.EndLocation
                        };
                    }

                }

            } else if (type >= TokenType.IntLiteral && type <= TokenType.FloatLiteral) {
                left = new NumberLiteral() {
                    StartLocation = _lexer.Read().StartLocation,
                    Type = type,
                    Value = _lexer.Current.LiteralBuffer.ToString()
                };
            } else if (type >= TokenType.StringLiteral && type <= TokenType.DataLiteral) {
                left = new StringLiteral() {
                    StartLocation = _lexer.Read().StartLocation,
                    Type = type,
                    Value = _lexer.Current.LiteralBuffer.ToString()
                };
            } else if (type >= TokenType.Typeof && type <= TokenType.Mul) {
                left = new UnaryExpression() {
                    StartLocation = _lexer.Read().StartLocation,
                    Operator = type,
                    Expression = ParseExpression(type.GetPrecedence())
                };
            } else {

                switch (type) {
                    case TokenType.NullLiteral:
                        left = new NullLiteral() {
                            StartLocation = _lexer.Read().StartLocation
                        };
                        break;
                    case TokenType.New:
                        left = ParseNewExpression();
                        break;
                    case TokenType.TrueLiteral:
                        left = new TrueLiteral() {
                            StartLocation = _lexer.Read().StartLocation
                        };
                        break;
                    case TokenType.FalseLiteral:
                        left = new FalseLiteral() {
                            StartLocation = _lexer.Read().StartLocation
                        };
                        break;
                    case TokenType.LBrack:
                        left = ParseListLiteral();
                        break;
                    case TokenType.LBrace:
                        left = ParseDictionaryLiteral();
                        break;
                    case TokenType.This:
                        left = new ThisLiteral() {
                            StartLocation = _lexer.Read().StartLocation
                        };
                        break;
                    case TokenType.Base:
                        left = new BaseLiteral() {
                            StartLocation = _lexer.Read().StartLocation
                        };
                        break;
                    case TokenType.Trace:
                        left = new TraceExpression() {
                            StartLocation = _lexer.Read().StartLocation,
                            Expression = ParseExpression(type.GetPrecedence())
                        };
                        break;
                    case TokenType.Div:
                    case TokenType.AssignDiv:
                        left = new RegExpLiteral() {
                            StartLocation = _lexer.Read().StartLocation,
                            Pattern = _lexer.ScanRegularExpressionBody(),
                            Flags = _lexer.ScanRegularExpressionFlags(),
                            EndLocation = _lexer.Current.EndLocation
                        };
                        break;
                    case TokenType.Assert: {
                            AssertExpression ret = new AssertExpression() {
                                StartLocation = _lexer.Read().StartLocation,
                                Expression = ParseExpression(type.GetPrecedence())
                            };
                            if (!_lexer.Current.HasLineTerminatorBeforeStart && MatchToken(TokenType.Throw)) {
                                ret.Throws = ParseExpression(type.GetPrecedence());
                            }
                            left = ret;
                        }
                        break;
                    case TokenType.Lambda:
                        left = ParseFunctionLiteral();
                        break;

                    default:

                        if (_lexer.Peek().HasLineTerminatorBeforeStart) {
                            Error("应该输入表达式。");
                        } else {
                            Error("{0} 不能作为表达式的一部分。", _lexer.Peek().LiteralBuffer.ToString());
                        }

                        left = new EmptyExpression() {
                            StartLocation = _lexer.Current.EndLocation
                        };
                        break;

                }
            }

            return ParseExpression(left, currentPrecedence);
        }

        private Expression ParseExpression(Expression left, byte currentPrecedence = 1) {

            //  PostfixExpression :
            //    LeftHandSideExpression
            //    LeftHandSideExpression [no LineTerminator here] ++
            //    LeftHandSideExpression [no LineTerminator here] --

            //  LeftHandSideExpression :
            //    NewExpression
            //    CallExpression

            //  NewExpression :
            //    MemberExpression
            //    new NewExpression

            //  MemberExpression :
            //    PrimaryExpression
            //    FunctionExpression
            //    MemberExpression [ Expression ]
            //    MemberExpression . Identifier
            //    MemberExpression . Identifier < GernicTypeList >
            //    new MemberExpression ( Arguments )

            byte precedence;
            TokenType type;

            // 依次处理优先级更小的操作符。
            while ((precedence = (type = _lexer.Peek().Type).GetPrecedence()) >= currentPrecedence) {

                if (type == TokenType.Period) {
                    left = new PropertyCallExpression() {
                        Target = left,
                        Argument = ParsePropertyCallArgument(),
                        EndLocation = _lexer.Current.EndLocation
                    };
                } else if (type == TokenType.LParam) {
                    left = new FunctionCallExpression() {
                        Target = left,
                        Arguments = ParseFunctionCallArguments(),
                        EndLocation = ExpectToken(TokenType.RParam).EndLocation
                    };
                } else if (type >= TokenType.Assign && type <= TokenType.AssignMod) {
                    _lexer.Read();
                    left = new AssignmentExpression() {
                        Left = left,
                        Operator = type,
                        Right = ParseExpression(precedence)
                    };
                } else if ((type >= TokenType.Pointer && type <= TokenType.OrReturn) || (type >= TokenType.Add && type <= TokenType.Mul)) {
                    _lexer.Read();
                    left = new BinaryExpression() {
                        Left = left,
                        Operator = type,
                        Right = ParseExpression((byte)(precedence + 1))
                    };
                } else {

                    switch (type) {
                        case TokenType.LBrack:
                            _lexer.Read();
                            left = new IndexCallExpression() {
                                Target = left,
                                Argument = ParseExpression(),
                                EndLocation = ExpectToken(TokenType.RBrack).EndLocation
                            };
                            break;
                        case TokenType.Lambda:

                            // 之前是一个普通的标识符，转换为函数定义表达式。
                            if (left is Identifier) {
                                left = ParseFunctionLiteral((Identifier)left);
                            } else {
                                Error("此处不应该有 {0}", _lexer.Current.LiteralBuffer.ToString());
                                return left;
                            }

                            break;

                        case TokenType.PeriodChain:
                            left = new ChainCallExpression() {
                                Target = left,
                                Argument = ParsePropertyCallArgument(),
                                EndLocation = _lexer.Current.EndLocation
                            };
                            break;
                        case TokenType.Conditional: {
                                _lexer.Read();

                                ConditionalExpression e = new ConditionalExpression {
                                    Condition = left,
                                };

                                e.ThenExpression = ParseExpression(precedence);
                                ExpectToken(TokenType.Colon);
                                e.ElseExpression = ParseExpression(precedence);
                                left = e;
                                break;
                            }
                        case TokenType.Comma: {
                                _lexer.Read();
                                ArrayLiteral arr = new ArrayLiteral() {
                                    StartLocation = left.StartLocation,
                                    Values = new List<Expression>() {
                                        left
                                    }
                                };
                                arr.Values.Add(ParseExpression(++precedence));
                                while (MatchToken(TokenType.Comma)) {
                                    arr.Values.Add(ParseExpression(precedence));
                                }
                                left = arr;
                                break;
                            }
                        case TokenType.Inc:
                        case TokenType.Dec:
                            if (!_lexer.Peek().HasLineTerminatorBeforeStart) {
                                left = new PostfixExpression {
                                    Expression = left,
                                    Operator = type,
                                    EndLocation = _lexer.Read().EndLocation
                                };
                                if (_lexer.Peek().HasLineTerminatorBeforeStart) {
                                    goto default;
                                }

                                break;
                            } else {
                                goto default;
                            }
                        default:
                            return left;
                    }
                }
            }

            return left;
        }

        private bool _seenGt = false;

        /// <summary>
        /// 当前是 Identifier 时，一直往下解析直到不再可能是类型的一部分为止。
        /// </summary>
        /// <param name="allowTypeIdentifier"></param>
        /// <returns></returns>
        private Expression ParseTypeOrExpression(bool allowTypeIdentifier) {

            //  Type :
            //    PredefinedType
            //    Identifier
            //    Identifier < TypeList >
            //    Identifier [ ]
            //    Identifier *
            //    Type . Type

            //  PredefinedType : one of
            //    int uint long ulong decimal short ushort byte sbyte bit float double string object

            //  TypeList :
            //    Type
            //    Type : Type
            //    TypeList , Type

            Expression left = new Identifier() {
                StartLocation = _lexer.Read().StartLocation,
                Name = _lexer.Current.LiteralBuffer.ToString(),
                EndLocation = _lexer.Current.EndLocation
            };

        parsenext:

            switch (_lexer.Peek().Type) {

                // Identifier.Identifier
                case TokenType.Period:
                    left = new PropertyCallExpression() {
                        Target = left,
                        Argument = ParsePropertyCallArgument(),
                        EndLocation = _lexer.Current.EndLocation
                    };
                    goto parsenext;

                // Identifier*
                case TokenType.Mul:
                    TokenType type = _lexer.Peek(1).Type;
                    // 如果当前位置的类型是用于声明一个变量的，那么 * 认为是类型的一部分。
                    if (allowTypeIdentifier && type == TokenType.Identifier || type >= TokenType.Add && type <= TokenType.OrReturn) {
                        left = new TypeExpression() {
                            StartLocation = left.StartLocation,
                            Left = left,
                            Operator = TokenType.Mul,
                            Right = null,
                            EndLocation = _lexer.Read().EndLocation
                        };
                        goto parsenext;
                    } else {
                        break;
                    }

                // Identifier[
                case TokenType.LBrack:
                    if (_lexer.Peek(1).Type == TokenType.RBrack) {
                        _lexer.Read();
                        left = new TypeExpression() {
                            StartLocation = left.StartLocation,
                            Left = left,
                            Operator = TokenType.LBrack,
                            Right = null,
                            EndLocation = _lexer.Read().EndLocation
                        };
                        goto parsenext;
                    } else {
                        break;
                    }

                // Identifier<
                case TokenType.Lt:
                    if (LookslikeGernicType()) {
                        // left = ParseGernicType(left);

                        _lexer.Read();

                        // 解析右半部分。
                        Expression right = ParseTypeOrExpression(false);

                        // 肯能是多成员的泛型。
                        if (MatchToken(TokenType.Comma)) {

                            ArrayLiteral arr = new ArrayLiteral() {
                                StartLocation = right.StartLocation,
                                Values = new List<Expression>() {
                                    right
                                }
                            };
                            do {
                                arr.Values.Add(ParseTypeOrExpression(false));
                            } while (MatchToken(TokenType.Comma));
                            right = arr;

                        }

                        if (_seenGt) {
                            _seenGt = false;
                            left = new TypeExpression() {
                                StartLocation = left.StartLocation,
                                Left = left,
                                Operator = TokenType.Lt,
                                Right = right,
                                EndLocation = _lexer.Current.EndLocation
                            };
                        } else if (MatchToken(TokenType.Gt)) {
                            left = new TypeExpression() {
                                StartLocation = left.StartLocation,
                                Left = left,
                                Operator = TokenType.Lt,
                                Right = right,
                                EndLocation = _lexer.Current.EndLocation
                            };
                        } else if (MatchToken(TokenType.Shr)) {
                            _seenGt = true;
                            return new TypeExpression() {
                                StartLocation = left.StartLocation,
                                Left = left,
                                Operator = TokenType.Lt,
                                Right = right,
                                EndLocation = _lexer.Current.EndLocation - 1
                            };
                        } else {
                            Error("应输入类型。");
                            break;
                        }

                        goto parsenext;
                    } else {
                        break;
                    }

            }


            return left;
        }

        /// <summary>
        /// 解析点之后的属性表达式。
        /// </summary>
        /// <returns></returns>
        private Expression ParsePropertyCallArgument() {
            _lexer.Read(); // 跳过 .
            TokenType type = _lexer.Peek().Type;
            switch (type) {
                case TokenType.Identifier:

                    // 表达式后面肯能紧跟 <> 符号。
                    if (_lexer.Peek(1).Type == TokenType.Lt && LookslikeGernicType()) {
                        return ParseTypeOrExpression(false);
                    } else {
                        return new Identifier() {
                            StartLocation = _lexer.Read().StartLocation,
                            Name = _lexer.Current.LiteralBuffer.ToString(),
                            EndLocation = _lexer.Current.EndLocation
                        };
                    }

                case TokenType.EOF:
                    Error("需要标识符");
                    return new EmptyExpression() {
                        StartLocation = _lexer.Peek().StartLocation
                    };

                default:

                    // 允许关键字作为标识符使用。
                    return new Identifier() {
                        StartLocation = _lexer.Read().StartLocation,
                        Name = _lexer.Current.LiteralBuffer.ToString(),
                        EndLocation = _lexer.Current.EndLocation
                    };

            }
        }

        private List<FunctionCallExpression.Argument> ParseFunctionCallArguments() {
            List<FunctionCallExpression.Argument> ret = new List<FunctionCallExpression.Argument>();

            _lexer.Read();

        parsenext:

            FunctionCallExpression.Argument argument = new FunctionCallExpression.Argument() {
                StartLocation = _lexer.Peek().StartLocation
            };
        skip:
            switch (_lexer.Peek().Type) {
                case TokenType.RParam:
                    _lexer.Read();
                    return ret;
                case TokenType.EOF:
                    break;
                case TokenType.Ref:
                    if (argument.ByRef) {
                        Error("Dump ref");
                    } else {
                        argument.ByRef = true;
                    }
                    _lexer.Read();
                    goto skip;
                case TokenType.Identifier:
                    if (_lexer.Peek(1).Type == TokenType.Colon) {
                        argument.Name = _lexer.Read().LiteralBuffer.ToString();
                        _lexer.Read();
                        goto default;
                    }

                    ret.Add(argument);

                    // argument.Value = ParseExpression((byte)(TokenType.Comma.GetPrecedence() + 1));
                    // 加速上一语句为：
                    argument.Value = ParseExpression(ParseTypeOrExpression(false), (byte)(TokenType.Comma.GetPrecedence() + 1));

                    if (MatchToken(TokenType.Comma)) {
                        goto parsenext;
                    }

                    break;
                default:

                    ret.Add(argument);
                    argument.Value = ParseExpression((byte)(TokenType.Comma.GetPrecedence() + 1));

                    if (MatchToken(TokenType.Comma)) {
                        goto parsenext;
                    }

                    break;
            }

            return ret;
        }

        private NewExpression ParseNewExpression() {
            NewExpression ret = new NewExpression() {
                StartLocation = _lexer.Read().StartLocation,
                Target = ParseTypeOrExpression(false)
            };

            if (_lexer.Peek().Type == TokenType.LParam) {
                ret.Arguments = ParseFunctionCallArguments();
            }

            ret.EndLocation = _lexer.Current.EndLocation;

            return ret;
        }

        private ListLiteral ParseListLiteral() {

            //  ListLiteral :
            //    [ Elision? ElementList? Elision? ]

            //  ElementList :
            //    AssignmentExpression
            //    ElementList Elision AssignmentExpression

            //  Elision :
            //    ,
            //    Elision ,

            ListLiteral ret = new ListLiteral() {
                StartLocation = _lexer.Read().StartLocation,
                Values = new List<Expression>()
            };

        redo:
            switch (_lexer.Peek().Type) {
                case TokenType.Comma:
                    _lexer.Read();
                    goto redo;
                case TokenType.RBrack:
                    break;
                default:
                    ret.Values.Add(ParseExpression((byte)(TokenType.Comma.GetPrecedence() + 1)));
                    goto redo;
            }

            ret.EndLocation = ExpectToken(TokenType.RBrack).EndLocation;

            return ret;

        }

        private DictionaryLiteral ParseDictionaryLiteral() {

            //  DictionaryLiteral :
            //    { }
            //    { Elision? PropertyNameAndValueList Elision? }

            //  PropertyNameAndValueList :
            //    PropertyName : AssignmentExpression
            //    PropertyNameAndValueList Elision PropertyName : AssignmentExpression

            //  PropertyName :
            //    Identifier
            //    StringLiteral
            //    NumericLiteral

            DictionaryLiteral ret = new DictionaryLiteral() {
                StartLocation = _lexer.Read().StartLocation,
                Values = new List<DictionaryLiteral.Property>()
            };

        redo:

            switch (_lexer.Peek().Type) {

                case TokenType.RBrace:
                    // case TokenType.Comma:
                    //  允许多余 }
                    _lexer.Read();
                    goto end;

                case TokenType.Comma:
                    _lexer.Read();
                    goto redo;

                case TokenType.EOF:
                    Error("缺少 }");
                    goto end;

                default:

                    Identifier key = new Identifier() {
                        StartLocation = _lexer.Read().StartLocation,
                        Name = _lexer.Current.LiteralBuffer.ToString(),
                        EndLocation = _lexer.Current.EndLocation
                    };

                    ExpectToken(TokenType.Colon);

                    ret.Values.Add(new DictionaryLiteral.Property() {
                        Key = key,
                        Value = ParseExpression((byte)(TokenType.Comma.GetPrecedence() + 1))
                    });

                    // 如果存在下一个属性。
                    if (MatchToken(TokenType.Comma))
                        goto redo;

                    ExpectToken(TokenType.RBrace);
                    break;
            }

        end:

            ret.EndLocation = _lexer.Current.EndLocation;

            return ret;
        }

        private Expression ParseFunctionLiteral(Identifier left = null) {

            //  FunctionLiteral:
            //    Identifier FunctionBody
            //    ( FunctionParamList? ) FunctionBody
            //    function Identifier? ( FunctionParamList? ) FunctionBody

            //  FunctionParamList
            //    FunctionParam
            //    FunctionParamList , FunctionParam

            //  FunctionParam :
            //    Identifier
            //    Identifier = Expression
            //    ref FunctionParam

            //  FunctionBody :
            //    => Statement
            //    Block

            FunctionLiteral fn = new FunctionLiteral();

            if (left != null) {
                fn.StartLocation = left.StartLocation;
                fn.Params = new List<FunctionLiteral.Param>() {
                        new FunctionLiteral.Param(){
                            StartLocation = left.StartLocation,
                            ByRef = false,
                            Type = null,
                            Name = left,
                            DefaultValue = null,
                            EndLocation = left.EndLocation
                        }
                    };
            } else {
                fn.StartLocation = _lexer.Peek().StartLocation;
                fn.Params = ParseFunctionParamList();
            }

            //switch (_lexer.Peek().Type) {
            //    case TokenType.Identifier:
            //        ps = new List<FunctionLiteral.Param>() {
            //            new FunctionLiteral.Param(_lexer.Read().StartLocation, null, _lexer.Current.LiteralBuffer.ToString(), _lexer.Current.EndLocation)
            //        };
            //        break;
            //    case TokenType.LParam:
            //        ps = ParseFunctionParamList();
            //        break;
            //    default:
            //        Error("需要参数列表");
            //        break;
            //}

            switch (_lexer.Peek().Type) {
                case TokenType.LBrace:
                    fn.Stype = left != null ? FunctionLiteral.FunctionStype.None : FunctionLiteral.FunctionStype.Function;
                    fn.Statement = ParseStatementExceptEmptyStatement();
                    break;
                case TokenType.Lambda:
                    _lexer.Read();
                    fn.Stype = left != null ? FunctionLiteral.FunctionStype.SingleParamLambda : FunctionLiteral.FunctionStype.Lambda;
                    fn.Statement = ParseStatementExceptEmptyStatement();
                    break;

                default:
                    Error("需要函数主体");
                    break;

            }

            return fn;
        }

        private List<FunctionLiteral.Param> ParseFunctionParamList() {

            // (params Type paramName, ...)
            // (ref Type paramName, ...)
            // (Type paramName, ...)
            // (paramName = Expression, ...)
            // (Expression)
            // (Type) 

            List<FunctionLiteral.Param> ret = new List<FunctionLiteral.Param>();

            if (_lexer.Read().Type == TokenType.LParam) {

                do {

                    if (MatchToken(TokenType.RParam)) {
                        return ret;
                    }

                    Location start = _lexer.Peek().StartLocation;
                    bool byRef = false;
                    Expression type;
                    Expression value;
                    Identifier name;

                    if (_lexer.Peek().Type == TokenType.Ref) {
                        _lexer.Read();
                        if (byRef) {
                            Error("多余的 ref");
                        } else {
                            byRef = true;
                        }
                    }

                    type = ParseExpression((byte)(TokenType.Comma.GetPrecedence() + 1));

                    if (_lexer.Peek().Type == TokenType.Identifier) {
                        name = new Identifier() {
                            StartLocation = _lexer.Read().StartLocation,
                            Name = _lexer.Current.LiteralBuffer.ToString(),
                            EndLocation = _lexer.Current.EndLocation
                        };
                    } else if (type is Identifier) {
                        name = (Identifier)type;
                        type = null;
                    } else {
                        name = null;
                        Error("缺少参数名");
                    }

                    if (_lexer.Peek().Type == TokenType.Assign) {
                        value = ParseExpression((byte)(TokenType.Comma.GetPrecedence() + 1));
                    } else {
                        value = null;
                    }

                    ret.Add(new FunctionLiteral.Param() {
                        StartLocation = start,
                        ByRef = byRef,
                        Type = type,
                        Name = name,
                        DefaultValue = value,
                        EndLocation = _lexer.Current.EndLocation
                    });

                } while (MatchToken(TokenType.Comma));

                ExpectToken(TokenType.RParam);

            }

            return ret;
        }

        #endregion

    }

}
